package com.quan.commons.utils;

import com.quan.system.commons.vo.SysSchedulerVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * Quartz 定时任务工具类
 *
 * @author Administrator
 */
@Slf4j
@Component
public class SchedulerUtils {

    @Autowired
    private Scheduler scheduler;

    /**
     * 新建定时任务
     *
     * @param vo
     */
    public void newJob(SysSchedulerVo vo) throws SchedulerException, ClassNotFoundException {

        // 开启新任务前，先删除原有的
        deleteJob(vo.getJobName(), vo.getJobGroup());

        log.info("==>【新建定时任务】" +
                        "任务名称：{}，" +
                        "任务组名称：{}，" +
                        "Cron表达式：{}，" +
                        "任务描述信息：{}，" +
                        "作业类：{}，" +
                        "作业参数：{}，" +
                        "任务状态：{}",
                vo.getJobName(),
                vo.getJobGroup(),
                vo.getJobCron(),
                vo.getJobDesc(),
                vo.getJobClassPath(),
                vo.getJobParams(),
                vo.getJobStatus());

        Class<Job> jobClass = getJobClass(vo.getJobClassPath());

        // 构建JOB信息
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(vo.getJobName(), vo.getJobGroup())
                .withDescription(vo.getJobDesc()).build();

        // 触发时间点
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(vo.getJobCron());
        // 触发器
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger-" + vo.getJobName(), vo.getJobGroup())
                .startNow().withSchedule(cronScheduleBuilder).build();

        // 添加JobDataMap数据
        if (null != vo.getJobDataMap()) {
            Map<String, Object> jobDataMap = vo.getJobDataMap();
            for (String key : jobDataMap.keySet()) {
                jobDetail.getJobDataMap().put(key, jobDataMap.get(key));
            }
        }

        // 交由Scheduler安排触发
        scheduler.scheduleJob(jobDetail, trigger);

    }

    /**
     * 暂停任务
     *
     * @param jobName
     * @param jobGroup
     */
    public void pauseJob(String jobName, String jobGroup) throws SchedulerException {
        log.info("==>【暂停任务】任务名称：{}，任务组名称：{}", jobName, jobGroup);
        JobKey jobKey = new JobKey(jobName, jobGroup);
        scheduler.pauseJob(jobKey);
    }

    /**
     * 恢复任务
     *
     * @param jobName
     * @param jobGroup
     */
    public void resumeJob(String jobName, String jobGroup) throws SchedulerException {
        log.info("==>【恢复任务】任务名称：{}，任务组名称：{}", jobName, jobGroup);
        JobKey jobKey = new JobKey(jobName, jobGroup);
        scheduler.resumeJob(jobKey);
    }

    /**
     * 触发任务
     *
     * @param jobName
     * @param jobGroup
     */
    public void triggerJob(String jobName, String jobGroup) throws SchedulerException {
        log.info("==>【触发任务】任务名称：{}，任务组名称：{}", jobName, jobGroup);

        JobKey jobKey = new JobKey(jobName, jobGroup);
        scheduler.triggerJob(jobKey);

    }

    /**
     * 删除任务
     *
     * @param jobName
     * @param jobGroup
     */
    public boolean deleteJob(String jobName, String jobGroup) throws SchedulerException {
        JobKey key = new JobKey(jobName, jobGroup);

        if(null != key && StringUtils.isNotBlank(key.getName())) {
            // 先暂停任务
            pauseJob(jobName, jobGroup);

            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);

            // 删除任务
            scheduler.deleteJob(key);
            log.info("==>【删除任务】任务名称：{}，任务组名称：{}", jobName, jobGroup);
            return false;
        } else {
            return true;
        }


    }

    private Class<Job> getJobClass(String jobClassPath) throws ClassNotFoundException {
        return (Class<Job>) Class.forName(jobClassPath);
    }

}
